// Copyright (C) 2008 Taylor L. Riche <riche@cs.utexas.edu>
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

#ifndef SYSTEM_H_
#define SYSTEM_H_

#include <assert.h>
#include <list>
#include <map>
#include <iostream>
#include <stdlib.h>
#include "ProcElement.h"
#include "CommChannel.h"
#include "Operator.h"
#include "MemGroup.h"

namespace lagniappe
{

const bool INITIAL = true;

class CommChannel;
class MemGroup;
class ProcElement;
class Operator;

class System
{
	
protected:
	std::map<std::string, ProcElement *> procMap;
	std::map<std::string, CommChannel *> chanMap;
	std::list<ProcElement *> freeProcList;
	std::map<std::string, ProcElement *>::iterator procIter;
	std::map<Operator *, std::list<ProcElement*> > opToProcMap;
	std::map<ProcElement*, std::list<Operator *> > procToOpMap;
	std::list<MemGroup *> memGroupList;
	std::map<Operator *, std::list<MemGroup *> > opToMemGroupMap;
public:
	System();
	virtual ~System();
	virtual void createResources() = 0;
	virtual ProcElement * createProfilerResources() = 0;
	virtual void destroyProfilerResources() = 0;
	virtual ProcElement * getFreeProc(Operator * o, bool initial = false);
	void addFreeProc(ProcElement * p);
	ProcElement * roundRobin();
	virtual Mutex * getNewMutex() = 0;
	void reportChannelUsage();
	void assignProc(ProcElement * p, Operator * o);
	void revokeProc(ProcElement * p, Operator * o);
	struct SwapStruct
	{
		SwapStruct() : foundSwap(false), targetProc(NULL), oldOp(NULL) {}
		bool foundSwap;
		ProcElement * targetProc;
		Operator * oldOp;
	};
	SwapStruct findSwap(Operator * o);
	
};

}

#endif /*SYSTEM_H_*/
